#include <vcl.h>
#include <stdio.h>
#include <StdLib.h>
#include <SysUtils.hpp>
#pragma hdrstop

#include <Dir.h>
#include <EIC.h>
#include "CVisuFichier.h"
#pragma package(smart_init)

#define MODULE_TAG 603

#define TAG_MARQUE_GAUCHE 0x0001
#define TAG_MARQUE_DROITE 0x0002

#define TAG_TRAIT         0x0010
#define TAG_TRAIT_GAUCHE  (TAG_TRAIT + TAG_MARQUE_GAUCHE)
#define TAG_TRAIT_DROIT   (TAG_TRAIT + TAG_MARQUE_DROITE)

#define PREFIXE_FIC_WINDOWS   "Driver EIC "
LRESULT CALLBACK _SubClassScrollBoxEditeur ( HWND hScrollBoxEditeur, UINT message, WPARAM wParam, LPARAM lParam);
using namespace std;
c_VisuFichier   VisuFichierList;


#define NB_PIXEL_BAS 1
//---------------------------------------------------------------------------
namespace Cvisufichier
{
	void __fastcall PACKAGE Register()
	{
		TComponentClass classes[1] = {__classid(CVisuFichier)};
		RegisterComponents("EIC Outils", classes, 0);
	}
}
//---------------------------------------------------------------------------
// ValidCtrCheck est utilisé pour être sûr que les composants créés ne
// contiennent aucune fonction virtuelle pure.
//

static inline void ValidCtrCheck(CVisuFichier *)
{
	new CVisuFichier(NULL);
}

void __fastcall CVisuFichier::WMOnCreate(Messages::TMessage &Message)
{
        FonctionScrollBoxEditeur = (FARPROC)GetWindowLong( ScrollBoxEditeur->Handle, GWL_WNDPROC);
        SetWindowLong( ScrollBoxEditeur->Handle, GWL_WNDPROC, (LONG)_SubClassScrollBoxEditeur);
        VisuFichierList.insert(c_VisuFichier::value_type(ScrollBoxEditeur->Handle,this));
}
/////////////////////////////////////////////////////////////////////////////
//                           CONSTRUCTEUR                                  //
//                INITIALISATION DES OBJETS CONTENUS                       //
//---------------------------------------------------------------------------
__fastcall CVisuFichier::CVisuFichier(TComponent* Owner)
	: TPanel(Owner)
{
	try
    {
        OnResize = PanelEditeurResize;
        BevelOuter = bvLowered;
        BevelInner = bvNone;
        m_TypeVisuFichier = etvf_SESAME;
        m_JeuCaracteres = ejdc_Windows;
        m_InversionVideo = true;
        m_DelimiteurChaine = m_DelimiteurColonne = '\0';
        ScrollBoxEditeur = new TScrollBox(this);
        ScrollBoxEditeur->Parent                  = this;
		ScrollBoxEditeur->Align                   = alClient;
		ScrollBoxEditeur->AutoScroll              = true;
		ScrollBoxEditeur->Color                   = clWhite;
		ScrollBoxEditeur->ParentColor             = false;
		ScrollBoxEditeur->ParentFont              = false;
        ScrollBoxEditeur->BorderStyle             = bsNone;

        ImageEditeur  = new TImage(this);
        ImageEditeur->Parent  = ScrollBoxEditeur;
        ImageEditeur->IncrementalDisplay = true;
        ImageEditeur->Width  = Width;
        ImageEditeur->Height = Height; // permet l'apparition des 2 barres de défilement
        ImageEditeur->Picture->Bitmap->Height = 0;
        ImageEditeur->Picture->Bitmap->Width  = 0;
        ImageEditeur->Canvas->Font->Name    = "Courier New";
        ImageEditeur->Canvas->Font->Size    = 9;
        ImageEditeur->Canvas->Font->Pitch   = fpFixed;
        MarqueGauche     = new TImage(this);
        MarqueGauche->Parent = ScrollBoxEditeur;
        MarqueGauche->Tag         = TAG_MARQUE_GAUCHE;
        MarqueGauche->Left        = 20;
        MarqueGauche->OnMouseDown = MarqueMouseDown;
        MarqueGauche->OnMouseMove = MarqueMouseMove;
        MarqueGauche->OnMouseUp   = MarqueMouseUp;
        MarqueGauche->Cursor      = crHSplit;
        ChargeMarque( MarqueGauche, "MARQUE_GAUCHE");

        MarqueDroite         = new TImage(this);
        MarqueDroite->Parent = ScrollBoxEditeur;
        MarqueDroite->Tag         = TAG_MARQUE_DROITE;
        MarqueDroite->Left        = 50;
        MarqueDroite->OnMouseDown = MarqueMouseDown;
        MarqueDroite->OnMouseMove = MarqueMouseMove;
        MarqueDroite->OnMouseUp   = MarqueMouseUp;
        MarqueDroite->Cursor      = crHSplit;
        ChargeMarque( MarqueDroite, "MARQUE_DROITE");

        TraitMarqueGauche  = new TImage(this);
        TraitMarqueGauche->Parent  = ScrollBoxEditeur;
        TraitMarqueGauche->Tag     = TAG_TRAIT_GAUCHE;
	    TraitMarqueGauche->Left    = MarqueGauche->Left + (MarqueGauche->Width - MarqueGauche->Left)/2;
	    TraitMarqueGauche->Top     = 0;
	    TraitMarqueGauche->Width   = 1;
	    TraitMarqueGauche->Stretch = true;
	    TraitMarqueGauche->Canvas->Brush->Color = clBlack;
    	TraitMarqueGauche->Canvas->FillRect( TraitMarqueGauche->Canvas->ClipRect);
        TraitMarqueGauche->OnMouseDown = MarqueMouseDown;
        TraitMarqueGauche->OnMouseMove = MarqueMouseMove;
        TraitMarqueGauche->OnMouseUp   = MarqueMouseUp;
        TraitMarqueGauche->Cursor      = crHSplit;

        TraitMarqueDroite  = new TImage(this);
        TraitMarqueDroite->Parent  = ScrollBoxEditeur;
        TraitMarqueDroite->Tag     = TAG_TRAIT_DROIT;
	    TraitMarqueDroite->Left    = MarqueDroite->Left + (MarqueDroite->Width - MarqueDroite->Left)/2;
	    TraitMarqueDroite->Top     = 0;
	    TraitMarqueDroite->Width   = 1;
	    TraitMarqueDroite->Stretch = true;
	    TraitMarqueDroite->Canvas->Brush->Color = clBlack;
    	TraitMarqueDroite->Canvas->FillRect( TraitMarqueDroite->Canvas->ClipRect);
        TraitMarqueDroite->OnMouseDown = MarqueMouseDown;
        TraitMarqueDroite->OnMouseMove = MarqueMouseMove;
        TraitMarqueDroite->OnMouseUp   = MarqueMouseUp;
        TraitMarqueDroite->Cursor      = crHSplit;

		PanelEditeurResize( this);
        m_Position = 5;
        m_Longueur = 5;
        ReplaceMarqueGauche();
        ReplaceMarqueDroite();
	}
    catch(...){}
}



void __fastcall CVisuFichier::Clear()
{
  ImageEditeur->Canvas->Brush->Color = clWindow;
  ImageEditeur->Canvas->FillRect(ImageEditeur->Canvas->ClipRect);
}



//---------------------------------------------------------------------------
__fastcall CVisuFichier::~CVisuFichier()
{
}

/////////////////////////////////////////////////////////////////////////////
//              INITIALISATION DES IMAGES DES MARQUES                      //
//---------------------------------------------------------------------------
void __fastcall CVisuFichier::ChargeMarque( TImage* Marque, AnsiString szNomBmp)
{
    Marque->Width  = 9;
    Marque->Height = 14;

    try{
        Graphics::TBitmap *pBmp = new Graphics::TBitmap();
        pBmp->LoadFromResourceName((int)HInstance, szNomBmp);
        pBmp->Transparent       = true;
        pBmp->TransparentColor  = pBmp->Canvas->Pixels[0][0];
        pBmp->TransparentMode   = tmFixed;
        Marque->Canvas->Draw( 0, 0, pBmp );
        delete pBmp;
    }
    catch( ...)
    {
    }

}


/////////////////////////////////////////////////////////////////////////////
//            INITIALISATION DE L'IMAGE CONTENANT LE FICHIER               //
//---------------------------------------------------------------------------
void __fastcall CVisuFichier::Afficher( )
{
  unsigned int TailleColonnes[100],Taille;
  bool bWriteSomething;
  int j,nNbCarMax = 0,x,y = 0;
  TStringList *ListeChamps = NULL;
  CTextFileStream *pfTxt = NULL;
  AnsiString message,BmpFile2,BmpFile,Ligne;
    try
      {
        Clear();
        if (m_szFicName.IsEmpty())
          {
            message = "  Aucun fichier à afficher.";
            goto FinAfficher;
          }
        if (!EICFileExist(m_szFicName))
          {
            message = "  Le fichier '" + m_szFicName + "' est introuvable.";
            goto FinAfficher;
          }
        pfTxt = new CTextFileStream( m_szFicName.c_str(), fmOpenRead	| fmShareDenyWrite);
        if( !pfTxt)
            return;

        switch (m_TypeVisuFichier)
          {
            case etvf_SESAME:
              // Récupère le nom du fichier contenant la bitmap
              pfTxt->ReadLine( BmpFile);
              if( BmpFile.SubString( 1, strlen(PREFIXE_FIC_WINDOWS)) != AnsiString( PREFIXE_FIC_WINDOWS))
                  message = "  Le fichier '" + m_szFicName + "' n'est pas un fichier provenant du pilote SESAME.";
              else
              {
                  BmpFile = BmpFile.SubString( strlen(PREFIXE_FIC_WINDOWS), BmpFile.Length() - strlen(PREFIXE_FIC_WINDOWS) + 1).Trim();
                  if (!EICFileExist(BmpFile))
                    {//Le fichier .bmp sité dans le .eic n'existe pas, on cherche dans le répertoire du .eic pour voir s'il n'y en a pas un
                      BmpFile2 = IncludeTrailingBackslash(ExtractFilePath(m_szFicName)) + ExtractFileName(BmpFile);
                      if (EICFileExist(BmpFile2))
                        BmpFile = BmpFile2;
                      else
                        {//On essaie maintenant de voir s'il existe un .bmp avec le même nom (à l'exception de l'extension) que le .eic
                          BmpFile2 = ChangeFileExt(m_szFicName,".bmp");
                          if (EICFileExist(BmpFile2))
                            BmpFile = BmpFile2;
                        }
                    }
                  if( EICFileExist( BmpFile))
                  {
                      // Visualisation de la bitmap représentant une page
                      ImageEditeur->AutoSize = true;
                      try
                      {
                          ImageEditeur->Picture->LoadFromFile( BmpFile);
                      }
                      catch(...){}

                      ImageEditeur->Picture->Bitmap->Monochrome = false;
                  }
                  else
                      message = "  Le fichier '" + BmpFile + "' est introuvable.";
              }
              break;
            default:
              ASSERT(false);
            case etvf_ASCII:
              #define LARG_DOS  2500
              ImageEditeur->AutoSize = true;
              ImageEditeur->Picture->Bitmap->Height = 1169;
              ImageEditeur->Picture->Bitmap->Width  = LARG_DOS;
              if (InversionVideo)
                {
                  ImageEditeur->Canvas->Font->Color   = clHighlightText;
                  ImageEditeur->Canvas->Brush->Color  = clHighlight;
                }
              else
                {
                  ImageEditeur->Canvas->Font->Color   = clWindowText;
                  ImageEditeur->Canvas->Brush->Color  = clWindow;
                }

              if (m_DelimiteurColonne)
                {//On affiche un fichier délimité. On cherche les colonnes pour calculer leur taille
                  y = abs(ImageEditeur->Canvas->Font->Height) + 3;  //On laisse la place pour afficher les numéros de colonne
                  ListeChamps = new TStringList();
                  ZeroMemory(TailleColonnes,sizeof(TailleColonnes));
                  while (y < ImageEditeur->Height)                                        //On lit le fichier une première fois...
                    {
                      if( !pfTxt->ReadLine( Ligne))
                        break;
                      Ligne = Ligne.TrimRight();
                      bWriteSomething = false;

                      if( Ligne.Length() > nNbCarMax)   nNbCarMax = Ligne.Length();
                      switch (m_JeuCaracteres)
                        {
                          default:
                            ASSERT(false);
                          case ejdc_Windows:
                            break;
                          case ejdc_DOS:
                            OemToChar(Ligne.c_str(), Ligne.c_str());
                            break;
                          case ejdc_MAC:
                            MACToChar(Ligne);
                            break;
                        }
                      LireChamps(Ligne.c_str(),ListeChamps,m_DelimiteurColonne,m_DelimiteurChaine);
                      for (int i = 0;i < ListeChamps->Count;i++)                         //...pour avoir la taille de chaque colonne
                        if (i < ARRAYSIZE(TailleColonnes))
                          {
                            Taille = CharToPixel(ListeChamps->Strings[i].Length());
                            TailleColonnes[i + 1] = TailleColonnes[i + 1] > Taille ? TailleColonnes[i + 1] : Taille;
                          }
                      y += abs(ImageEditeur->Canvas->Font->Height) + 1;
                    }
                  for (int i = 0;i < ARRAYSIZE(TailleColonnes);i++)
                    {
                      if (TailleColonnes[i] == 0)
                        TailleColonnes[i] = CharToPixel(2);     //On met un largeur minimum de 2 caractères pour les colonnes afin de pouvoir afficher le numéro de colonne
                      if (i)
                        TailleColonnes[i] += TailleColonnes[i - 1] + CharToPixel(1);  //On calcule la position de chaque colonne
                    }
                  pfTxt->Seek(soFromBeginning,0);
                  y = abs(ImageEditeur->Canvas->Font->Height) + 3;  //On laisse la place pour afficher les numéros de colonne
                  while (y < ImageEditeur->Height)
                    {
                      if( !pfTxt->ReadLine( Ligne))
                        break;
                      Ligne = Ligne.TrimRight();
                      bWriteSomething = false;

                      switch (m_JeuCaracteres)
                        {
                          default:
                            ASSERT(false);
                          case ejdc_Windows:
                            break;
                          case ejdc_DOS:
                            OemToChar(Ligne.c_str(), Ligne.c_str());
                            break;
                          case ejdc_MAC:
                            MACToChar(Ligne);
                            break;
                        }
                      LireChamps(Ligne.c_str(),ListeChamps,m_DelimiteurColonne,m_DelimiteurChaine);
                      //1er passage pour déterminer la largeur max du fichier
                      for (int i = 0;i < ListeChamps->Count;i++)
                        if (i < ARRAYSIZE(TailleColonnes))
                          {
                            x = TailleColonnes[i];
                            x = PixelToChar(x) + ListeChamps->Strings[i].Length();
                            if (x > nNbCarMax)                                               //On calcule la largeur max du fichier
                              nNbCarMax = x;
                            ImageEditeur->Picture->Bitmap->Width  = CharToPixel( nNbCarMax+1);
                          }
                      for (int i = 0;i < ListeChamps->Count;i++)
                        if (i < ARRAYSIZE(TailleColonnes))
                          {
                            x = TailleColonnes[i];
                            if (i)
                              {
                                ImageEditeur->Canvas->Font->Color = clGreen;
                                ImageEditeur->Canvas->TextOut(x,y,m_DelimiteurColonne);
                                x += CharToPixel(1);
                              }
                            ImageEditeur->Canvas->Font->Color = clWindowText;
                            ImageEditeur->Canvas->TextOut(x,y,ListeChamps->Strings[i]);      //On affiche le texte de chaque colonne
                            //x = PixelToChar(x) + ListeChamps->Strings[i].Length();
                            //if (x > nNbCarMax)                                               //On calcule la largeur max du fichier
                            //  nNbCarMax = x;
                          }
                      y += abs(ImageEditeur->Canvas->Font->Height) + 1;
                    }
                  delete ListeChamps;
                  ListeChamps = NULL;
                  nNbCarMax += 2;
                  ImageEditeur->Canvas->Font->Color = clWindowText;
                  ImageEditeur->Canvas->Font->Style = ImageEditeur->Canvas->Font->Style << fsBold;
                  ImageEditeur->Canvas->Brush->Color = clBtnFace;
                  //ImageEditeur->Canvas->FillRect(TRect(0,0,LARG_DOS,16));
                  ImageEditeur->Canvas->FillRect(TRect(0,0,ImageEditeur->Picture->Bitmap->Width,16));
                  ImageEditeur->Canvas->Pen->Color = clWhite;
                  for (int i = 0;i < ARRAYSIZE(TailleColonnes) - 1;i++)
                    {
                      x = TailleColonnes[i];
                      if (i)
                        {
                          x += CharToPixel(1) / 2;
                          ImageEditeur->Canvas->MoveTo(x,0);
                          ImageEditeur->Canvas->LineTo(x,15);
                          x = TailleColonnes[i] + CharToPixel(1);
                        }
                      /*if (x > LARG_DOS)
                        break;*/
                      ImageEditeur->Canvas->TextOut(x,0,IntToStr(i + 1));    //On affiche chaque numéro de colonne
                    }
                  ImageEditeur->Canvas->Font->Style = ImageEditeur->Canvas->Font->Style >> fsBold;
                  ImageEditeur->Canvas->Brush->Color = clWindow;
                }
              else
                {
                  while( y < ImageEditeur->Height)
                  {   	/* On récupère la ligne*/
                      if( !pfTxt->ReadLine( Ligne))
                      {
                          ImageEditeur->Picture->Bitmap->Height = y;
                          break;
                      }
                      Ligne = Ligne.TrimRight();
                      bWriteSomething = false;

                      if( Ligne.Length() > nNbCarMax)   nNbCarMax = Ligne.Length();
                      switch (m_JeuCaracteres)
                        {
                          default:
                            ASSERT(false);
                          case ejdc_Windows:
                            break;
                          case ejdc_DOS:
                            OemToChar(Ligne.c_str(), Ligne.c_str());
                            break;
                          case ejdc_MAC:
                            MACToChar(Ligne);
                            break;
                        }
                      for( int i = 1; i <= Ligne.Length( ); i++)
                      {
                          if( ((unsigned char)Ligne[ i] > (unsigned char)' '))
                          {
                              for( j = i;
                                   ((j) <= Ligne.Length()) &&
                                   ((unsigned char)Ligne[ j] != (unsigned char)' ');
                                   j++)
                              {
                                  while( ( j <= Ligne.Length() )                        &&
                                         ((unsigned char)Ligne[ j] > (unsigned char)' ')  )
                                      j++;
                              }
                              j--;
                              if( j - i)
                              {
                                  int x = CharToPixel( i-1);
                                  bWriteSomething = true;
                                  ImageEditeur->Canvas->TextOut( x, y, Ligne.SubString( i, j - i) );
                              }
                              i = j;
                          }
                      }
                      if( y || bWriteSomething )
                          y += abs(ImageEditeur->Canvas->Font->Height)+1;
                  }
                  ImageEditeur->Picture->Bitmap->Width  = min( CharToPixel( nNbCarMax+1), LARG_DOS);
                }
              if( ScrollBoxEditeur->HorzScrollBar)
                  ImageEditeur->Left = CharToPixel( 1) - ScrollBoxEditeur->HorzScrollBar->Position;
              else
                  ImageEditeur->Left  = CharToPixel( 1);
              //ImageEditeur->Picture->Bitmap->Width  = min( CharToPixel( nNbCarMax+1), LARG_DOS);
              break;
          }
FinAfficher:
        if (!message.IsEmpty())
          {
            tagSIZE s = ImageEditeur->Canvas->TextExtent( message);
            ImageEditeur->Height = s.cy + 5;
            ImageEditeur->Width  = s.cx + 1;
            ImageEditeur->Picture->Bitmap->Height = ImageEditeur->Height;
            ImageEditeur->Picture->Bitmap->Width  = ImageEditeur->Width;
            ImageEditeur->Canvas->Font->Color   = clRed;
            ImageEditeur->Canvas->Brush->Color  = clWhite;
            ImageEditeur->Canvas->TextOut(0, 5, message);
          }
        if (pfTxt)
          {
            delete pfTxt;
            pfTxt = NULL;
          }
        if( ScrollBoxEditeur->HorzScrollBar)
	        ScrollBoxEditeur->HorzScrollBar->Tracking = true;
        if( ScrollBoxEditeur->VertScrollBar)
	        ScrollBoxEditeur->VertScrollBar->Tracking = true;

        PanelEditeurResize( this);
        ReplaceMarqueGauche();
        ReplaceMarqueDroite();
    }
    catch(...)
    {
      delete pfTxt;
      delete ListeChamps;
    }
}
//---------------------------------------------------------------------------
bool __fastcall CVisuFichier::LireChamps(char *szBuffer,TStringList *ListeChamps,char SeparateurChamp,char DelimChaine)
{
  bool Ok = false;
  int Position = 0;
  AnsiString Chaine;
  try
    {
      ListeChamps->Clear();
      while (LireChamp(szBuffer,Position,Chaine,SeparateurChamp,DelimChaine))
        ListeChamps->Add(Chaine.Trim());
      Ok = ListeChamps->Count;
    }
  catch (Exception &e)
    {
      EICDisplayException(TAGL,e);
    }
  return Ok;
}



bool __fastcall CVisuFichier::LireChamp(char *szBuffer,int &Position,AnsiString &Chaine,char SeparateurChamp,char DelimChaine)
{
  int PositionDebut = Position;
  bool ChercherSeparateurChamp = true,FinLigne = false;
  Chaine = EmptyStr;
  while (true)
    {
      switch (szBuffer[Position])
        {
          case '\0':
          case '\r':
          case '\n':
            FinLigne = true;
            break;                                           //On est à la fin de la ligne
          default:
            if (ChercherSeparateurChamp)
              {//On recherche un séparateur de champ
                if (szBuffer[Position] == SeparateurChamp)
                  break;                                     //On est à la fin du champ
                if (DelimChaine && (szBuffer[Position] == DelimChaine))
                  ChercherSeparateurChamp = false;           //On commence une chaine
              }
            else
              {//On recherche la fin d'une chaine
                if (szBuffer[Position] == DelimChaine)
                  ChercherSeparateurChamp = true;            //On termine une chaine
              }
            Position++;
            continue;
        }
      break;
    }
  if (PositionDebut != Position)
    Chaine = AnsiString(szBuffer + PositionDebut,Position - PositionDebut).Trim();
  if (szBuffer[Position] == SeparateurChamp)
    Position++;                                              //On place le pointeur sur le prochain champ
/* On laisse les délimiteur pour Karen qui l'a demandé pour l'import
  if (DelimChaine)
    for (int i = Chaine.Length();i > 0;i--)
      if (Chaine[i] == DelimChaine)
        Chaine.Delete(i,1); */                                  //On enlève les délimiteurs de la chaine
  return !(Chaine.IsEmpty() && FinLigne);
}



/////////////////////////////////////////////////////////////////////////////
//         INITIALISATION DES VARIABLES CHANGEES PAR L'UTILISATEUR         //
//---------------------------------------------------------------------------
void __fastcall CVisuFichier::SetPosition( int nPosition)
{
    if( m_Position == nPosition) return;
    int nPosDroite = m_Position + m_Longueur;
	m_Position = max( 0, min(nPosition, PixelToChar( ImageEditeur->Width)));
    ReplaceMarqueGauche();

    int nLong = m_Longueur;
    m_Longueur = max( 1, min(PixelToChar(MarqueDroite->Left - MarqueGauche->Left), PixelToChar( ImageEditeur->Width)-1-m_Position));
    if( (nLong != m_Longueur) && m_OnLongueurChange)
      {
        m_OnPositionChange( this);
        m_OnLongueurChange( this);
      }

    if( nPosDroite != (m_Position + m_Longueur))       ReplaceMarqueDroite();
}
//---------------------------------------------------------------------------
void __fastcall CVisuFichier::SetLongueur(int nLongueur)
{
  int nPos;
  if (m_Longueur == nLongueur)
    return;
  nPos = min(nLongueur,PixelToChar(ImageEditeur->Width) - 1 - m_Position);
  if (nPos < 1)
    {
      SetPosition(m_Position - 1);
      SetLongueur(1);
    }
  else
    {
     	m_Longueur = max(1,nPos);
      ReplaceMarqueDroite();
      if (m_OnLongueurChange)
        m_OnLongueurChange(this);
    }
}



/////////////////////////////////////////////////////////////////////////////
//  DessineLigne()
//  Dessin ligne vertical dans la zone d'édition à partir du pointeur gauche
void __fastcall CVisuFichier::_ReplaceMarque( bool bGauche)
{
    if( bGauche)
    {
    	TraitMarqueGauche->Left  = CharToPixel( m_Position) + ImageEditeur->Left;
	    MarqueGauche->Left = TraitMarqueGauche->Left - MarqueGauche->Width/2;
        if( (TraitMarqueGauche->Left < CharToPixel(1)) && ScrollBoxEditeur->HorzScrollBar)
          ScrollBoxEditeur->HorzScrollBar->Position = CharToPixel( m_Position) + ImageEditeur->Left;
    }else
    {
    	TraitMarqueDroite->Left  = CharToPixel( m_Position + m_Longueur) + ImageEditeur->Left;
	    MarqueDroite->Left = TraitMarqueDroite->Left - MarqueDroite->Width/2;
        if(    ((TraitMarqueDroite->Left - TraitMarqueGauche->Left)  < (ScrollBoxEditeur->Width - CharToPixel(1)))
            && ((TraitMarqueDroite->Left + TraitMarqueDroite->Width) > (ScrollBoxEditeur->Width - CharToPixel(1)))
            && ScrollBoxEditeur->HorzScrollBar )
          ScrollBoxEditeur->HorzScrollBar->Position += ( TraitMarqueDroite->Left + TraitMarqueDroite->Width - (ScrollBoxEditeur->Width - CharToPixel(1)));
    }
  if (OnPositionChange)
    OnPositionChange(this);
  if (OnLongueurChange)
    OnLongueurChange(this);
}



/////////////////////////////////////////////////////////////////////////////
//             FONCTIONS DE GESTION DE LA SOURIS SUR UNE MARQUE            //
//---------------------------------------------------------------------------
void __fastcall CVisuFichier::MarqueMouseDown(TObject *Sender,TMouseButton Button,TShiftState Shift,int X,int Y)
{
 	FDragging = true;
}
//---------------------------------------------------------------------------
void __fastcall CVisuFichier::MarqueMouseMove(TObject *Sender,TShiftState Shift,int X,int Y)
{
	if ( !FDragging) return;
         /* X et Y sont exprimées par rapport à la marque */
		/* On déplace la position */
    if( ((TImage*)Sender)->Tag & TAG_MARQUE_GAUCHE)
    {
	    SetPosition( m_Position + (PixelToChar(X)/*/max(1,PixelToChar(1))*/));   //Supprimé par David le 10/07/01
	  	if( m_OnPositionChange)   m_OnPositionChange( this);
    }
    else
    {
        SetLongueur( m_Longueur + (PixelToChar(X)/*/max(1,PixelToChar(1))*/)); //Supprimé par David le 10/07/01
        if( m_OnLongueurChange)   m_OnLongueurChange( this);
    }

}
//---------------------------------------------------------------------------
void __fastcall CVisuFichier::MarqueMouseUp(TObject *Sender,TMouseButton Button,TShiftState Shift,int X,int Y)
{
  FDragging = false;
}



//---------------------------------------------------------------------------
// ScrollBarScroll()
// Paramétrage Balance
// Evénement OnScroll sur barre de scrolling verticale
//---------------------------------------------------------------------------
void __fastcall CVisuFichier::ScrollBarScroll(TObject *Sender,TScrollCode ScrollCode,int &ScrollPos)
{
    ImageEditeur->Top = -ScrollPos;
}



/////////////////////////////////////////////////////////////////////////////
//           FONCTIONS DE CONVERSION  PIXEL -> CHAR (et inversement)       //
//---------------------------------------------------------------------------
//   PixelToChar()
// Conversion nombre de pixels en nombre de caractères
int __fastcall CVisuFichier::PixelToChar(int nNbPixel)
{
  switch (m_TypeVisuFichier)
    {
      case etvf_SESAME:
        return nNbPixel;
      default:
        ASSERT(false);
      case etvf_ASCII:
        return nNbPixel / max(1,ImageEditeur->Canvas->TextWidth("A"));
    }
}
//---------------------------------------------------------------------------
//   CharToPixel()
// Conversion nombre de caractères en nombre de pixels
int __fastcall CVisuFichier::CharToPixel(int nNbChar)
{
  switch (m_TypeVisuFichier)
    {
      case etvf_SESAME:
        return nNbChar;
      default:
        ASSERT(false);
      case etvf_ASCII:
        return nNbChar * ImageEditeur->Canvas->TextWidth("A");
    }
} 



//---------------------------------------------------------------------------
void __fastcall CVisuFichier::PanelEditeurResize(TObject *Sender)
{
    int nHeightHScroll = GetSystemMetrics( SM_CYHSCROLL),
        nScrollWidth   = ScrollBoxEditeur->Width - GetSystemMetrics( SM_CXHSCROLL);
    int nVScroll = 0;
    if( (ImageEditeur->Width + CharToPixel( 1)) <= nScrollWidth) nHeightHScroll = 0;

    MarqueGauche->Top  = nVScroll + ScrollBoxEditeur->Height - nHeightHScroll - MarqueGauche->Height - NB_PIXEL_BAS;
    MarqueDroite->Top  = nVScroll + ScrollBoxEditeur->Height - nHeightHScroll - MarqueDroite->Height - NB_PIXEL_BAS;

    TraitMarqueGauche->Top    = 0;
    TraitMarqueDroite->Top    = 0;
    TraitMarqueGauche->Height = MarqueGauche->Top;
    TraitMarqueDroite->Height = MarqueDroite->Top;
}


LRESULT CALLBACK _SubClassScrollBoxEditeur( HWND hScrollBox, UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT      lResultat;
    CVisuFichier *pVisuFichier = VisuFichierList[ hScrollBox];

    if( pVisuFichier && (pVisuFichier->FonctionScrollBoxEditeur != (FARPROC)0L))
        lResultat = CallWindowProc( pVisuFichier->FonctionScrollBoxEditeur, hScrollBox, message, wParam, lParam);
    else
        ASSERT( false);

    if( message == WM_VSCROLL)
    {
        if( pVisuFichier) pVisuFichier->PanelEditeurResize( NULL);
    }
    else if( message == WM_DESTROY)
    {
        if( pVisuFichier && (pVisuFichier->FonctionScrollBoxEditeur != (FARPROC)0L))
            SetWindowLong( pVisuFichier->ScrollBoxEditeur->Handle, GWL_WNDPROC, (LONG)pVisuFichier->FonctionScrollBoxEditeur);
        if (!VisuFichierList.empty()) VisuFichierList.erase(hScrollBox);
    }
    return ( lResultat);
}/* SubClassComboGestImmo() */

